package itsm.isperp.framework.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.Map;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.io.DocumentResult;
import org.dom4j.io.DocumentSource;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.SAXValidator;
import org.dom4j.io.XMLWriter;
import org.dom4j.util.XMLErrorHandler;

/**
 * 
 * 
 * @author lizx
 * @date 2013-4-24
 */
public class Dom4jUtils {

	private static final Log logger = LogFactory.getLog(Dom4jUtils.class);

	public static Document loadXml(String s) throws DocumentException {
		Document document = null;
		document = DocumentHelper.parseText(s);
		return document;
	}

	public static Document loadXml(String xml, String encode) {
		ByteArrayInputStream inputStream;
		try {
			inputStream = new ByteArrayInputStream(xml.getBytes(encode));
			return loadXml(((InputStream) (inputStream)), encode);
		} catch (UnsupportedEncodingException e) {
			return null;
		}

	}

	public static Document loadXml(InputStream is) {
		return loadXml(is, "utf-8");
	}

	public static Document loadXml(InputStream is, String charset) {
		Document document = null;
		try {
			SAXReader reader = new SAXReader();
			reader.setEncoding(charset);
			document = reader.read(is);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return document;
	}

	public static String transFormXsl(String xml, String xsl,
			Map<String, String> map) throws Exception {
		StringReader xmlReader = new StringReader(xml);
		StringReader xslReader = new StringReader(xsl);
		TransformerFactory factory = TransformerFactory.newInstance();
		Transformer transformer = factory.newTransformer(new StreamSource(
				xslReader));
		if (map != null) {
			Map.Entry<String, String> obj;
			for (Iterator<Map.Entry<String, String>> it = map.entrySet()
					.iterator(); it.hasNext(); transformer.setParameter(
					(String) obj.getKey(), obj.getValue()))
				obj = it.next();

		}
		StreamSource xmlSource = new StreamSource(xmlReader);
		StringWriter writer = new StringWriter();
		javax.xml.transform.Result result = new StreamResult(writer);
		transformer.transform(xmlSource, result);
		return writer.toString();
	}

	public static String transXmlByXslt(String xml, String xslPath,
			Map<String, String> map) throws Exception {
		Document document = loadXml(xml);
		Document result = styleDocument(document, xslPath, map);
		return docToString(result);
	}

	public static String docToString(Document document) {
		String s = "";
		try {
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			OutputFormat format = new OutputFormat("  ", true, "UTF-8");
			XMLWriter writer = new XMLWriter(out, format);
			writer.write(document);
			s = out.toString("UTF-8");
		} catch (Exception ex) {
			logger.error((new StringBuilder()).append("docToString error:")
					.append(ex.getMessage()).toString());
		}
		return s;
	}

	public static Document styleDocument(Document document, String stylesheet,
			Map<String, String> map) throws Exception {
		TransformerFactory factory = TransformerFactory.newInstance();
		Transformer transformer = factory.newTransformer(new StreamSource(
				stylesheet));
		if (map != null) {
			Map.Entry<String, String> obj;
			for (Iterator<Map.Entry<String, String>> it = map.entrySet()
					.iterator(); it.hasNext(); transformer.setParameter(
					(String) obj.getKey(), obj.getValue()))
				obj = it.next();

		}
		DocumentSource source = new DocumentSource(document);
		DocumentResult result = new DocumentResult();
		transformer.transform(source, result);
		Document transformedDoc = result.getDocument();
		return transformedDoc;
	}

	public static String validXmlBySchema(String xml, String schema) {
		String result = "";
		try {
			XMLErrorHandler errorHandler = new XMLErrorHandler();
			SAXParserFactory factory = SAXParserFactory.newInstance();
			factory.setValidating(true);
			factory.setNamespaceAware(true);
			SAXParser parser = factory.newSAXParser();
			SAXReader xmlReader = new SAXReader();
			Document xmlDocument = xmlReader.read(new File(xml));
			parser.setProperty(
					"http://java.sun.com/xml/jaxp/properties/schemaLanguage",
					"http://www.w3.org/2001/XMLSchema");
			parser.setProperty(
					"http://java.sun.com/xml/jaxp/properties/schemaSource",
					(new StringBuilder()).append("file:").append(schema)
							.toString());
			SAXValidator validator = new SAXValidator(parser.getXMLReader());
			validator.setErrorHandler(errorHandler);
			validator.validate(xmlDocument);
			XMLWriter writer = new XMLWriter(OutputFormat.createPrettyPrint());
			if (errorHandler.getErrors().hasContent())
				result = "<result success='0'>XML\u6587\u4EF6\u901A\u8FC7XSD\u6587\u4EF6\u6821\u9A8C\u5931\u8D25,\u8BF7\u68C0\u67E5xml\u662F\u5426\u7B26\u5408\u6307\u5B9A\u683C\u5F0F!</result>";
			else
				result = "<result success='1'>XML\u6587\u4EF6\u901A\u8FC7XSD\u6587\u4EF6\u6821\u9A8C\u6210\u529F!</result>";
		} catch (Exception ex) {
			result = (new StringBuilder())
					.append("<result success='0'>XML\u6587\u4EF6\u901A\u8FC7XSD\u6587\u4EF6\u6821\u9A8C\u5931\u8D25:")
					.append(ex.getMessage()).append("</result>").toString();
		}
		return result;
	}

}